let syntax = {
    Program: [["StatementList", "EOF"]],
    StatementList: [
        ["Statement"], 
        ["StatementList", "Statement"]
    ],
    Statement: [
        ["ExpressionStatement"],// 表达式
        ["Ifstatement"],
        ["VariableDeclaration"],
        ["FunctionDeclaration"],
    ],
    Ifstatement: [
        ["if", "(", "Expression", ")", "Statement"]
    ],
    VariableDeclaration: [
        ["var", "Identifier"]
    ],
    FunctionDeclaration: [
        ["function", "Identifier", "(", ")", "{", "StatementList" ,"}"]
    ],
    ExpressionStatement: [
        ["Expression", ";"]
    ],
    Expression: [
        ["AdditiveExpression"]
    ],
    AdditiveExpression: [
        ["MultiplicativeExpression"],
        ["AdditiveExpression" ,"+", "MultiplicativeExpression"],
        ["AdditiveExpression" ,"-", "MultiplicativeExpression"],
    ],
    MultiplicativeExpression: [
        ["PrimaryExpression"],
        ["MultiplicativeExpression", "*" , "PrimaryExpression"],
        ["MultiplicativeExpression", "/" , "PrimaryExpression"]
    ],
    PrimaryExpression: [
        ["(", "Expression", ")"],
        ["Literal"],
        ["Identifier"],
    ],
    Literal: [
        ["Number"],
        ["String"],
        ["Boolean"],
        ["Null"]
    ]
};

let hash = {

}; 
// 广度优先搜索
function closure(state) {
    hash[JSON.stringify(state)] = state;
    let queue = [];
    for(let symbol in state){
        queue.push(symbol);
    }

    while(queue.length) {
        let symbol = queue.shift();
        console.log(symbol);
        if(syntax[symbol]){ // 非eof
            for(let rule of syntax[symbol] ){
                if(!state[rule[0]]){
                    queue.push(rule[0]);
                }
                // state[rule[0]] = true;
                let current = state; // current 引用赋值 指向 state
                for(let part of rule)
                {
                    if(!current[part]){
                        current[part] = {}; // 由于引用赋值 ,等同于state[part] = {}
                    }
                    current = current[part]; // current 此时有改变了引用位置 指向了state[part], 循环后, current 下会生成一个树, 数的每个子节点分别是part 
                }
                current.$isRuleEnd = true; // 此处修改等同于 state[part][isRuleEnd] = true;
            }
        }
        
    }

    for(let symbol in state){
        if(hash[JSON.stringify(state[symbol])]){
            state[symbol] = hash[JSON.stringify(state[symbol])];
        }else{
            closure(state[symbol]);
        }
    }
};

let end = {
    $isEnd: true
}

let start = {
    Ifstatement: end
}


closure(start);
